package edu.gatech.cs2340.OregonTrail;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;

import javax.swing.JOptionPane;
import javax.xml.parsers.ParserConfigurationException;

import org.xml.sax.SAXException;

import edu.gatech.cs2340.OregonTrail.EventSystem.AtLocationEvent;
import edu.gatech.cs2340.OregonTrail.EventSystem.AtShopEvent;
import edu.gatech.cs2340.OregonTrail.EventSystem.CommCoordinator;

/**
 * Game class represents the primary game engine for driving the game
 * @author Tyler Johnston
 * @version 1.0.1
 *Object[]itemList = playerParty.getPlayer().getInventory().getStock().keySet().toArray();
 */
public class Game {
	private SettingManager gameSettings;
	private Party playerParty;
	private CommCoordinator comm;
	private ItemLoader itemLoader;
	private Trail trail;
	private int day = 0;
	private int fee;
	private Random generator;
	private Object[] itemList;
	private Map<Item, Integer> playerStock;
	private int chance;
	private int numToRemove;
	private Item toRemove;
	private RandomEventGenerator eventGenerator;
	
	
	/**
	 * Primary constructor for game class. Initializes gameSettings
	 */
	public Game(CommCoordinator comm){
		itemLoader = new ItemLoader();

		try {
			itemLoader.loadItems("ItemXML.xml");
		} catch (SAXException e) {
			JOptionPane.showMessageDialog(null, "Hey, the parser broke. Fix it");
			e.printStackTrace();
		} catch (ParserConfigurationException e) {
			JOptionPane.showMessageDialog(null, "Hey, the parser broke. Fix it. The configuration messed up");
			e.printStackTrace();
		} catch (IOException e) {
			JOptionPane.showMessageDialog(null, "Hey, the parser broke. Fix it. The file couldn't open");
			e.printStackTrace();
		}
		
		trail = new Trail(comm);
		gameSettings = new SettingManager();
		playerParty = null;
		this.comm = comm;
	}
	
	//double check on this
	public void intitalizeLoad(Party newParty, ePace pace, eRation ration){
		playerParty = newParty;
		Player player = playerParty.getPlayer();
		player.addCommunicator(comm);
		
		//this will have to be mirrored in load too. This setup is dumb
		this.eventGenerator = new RandomEventGenerator(comm, playerParty.getPlayer().getBreakC(),
				playerParty.getPlayer().getSickC());
		
		if(pace != null){
			gameSettings.setPace(pace);
		}
		
		if(ration != null){
			gameSettings.setRation(ration);
		}
		
		if(!itemLoader.getItems().isEmpty()){
			Map<Item, Integer> shopItems = new HashMap<Item, Integer>();
			Map<Item, Integer> playerItems = new HashMap<Item, Integer>();
			for(int i = 0; i < itemLoader.getItems().size(); i++){
				shopItems.put((Item)itemLoader.getItems().get(i), Integer.MAX_VALUE);
				playerItems.put((Item)itemLoader.getItems().get(i), 0);
			}
			
			player.addInventory(new PlayerInventory(playerItems, comm));
			
		}
	}

	/**
	 * Initializes the game engine with new game settings
	 * @param newParty Party to use as this game's party
	 * @param pace Initial pace to use
	 * @param ration Initial rations to use
	 */
	public void initializeNewGame(Party newParty, ePace pace, eRation ration){
		playerParty = newParty;
		Player player = playerParty.getPlayer();
		player.addCommunicator(comm);
		
		//this will have to be mirrored in load too. This setup is dumb
		this.eventGenerator = new RandomEventGenerator(comm, playerParty.getPlayer().getBreakC(),
				playerParty.getPlayer().getSickC());
		
		if(pace != null){
			gameSettings.setPace(pace);
		}
		
		if(ration != null){
			gameSettings.setRation(ration);
		}
		
		if(!itemLoader.getItems().isEmpty()){
			Map<Item, Integer> shopItems = new HashMap<Item, Integer>();
			Map<Item, Integer> playerItems = new HashMap<Item, Integer>();
			for(int i = 0; i < itemLoader.getItems().size(); i++){
				shopItems.put((Item)itemLoader.getItems().get(i), Integer.MAX_VALUE);
				playerItems.put((Item)itemLoader.getItems().get(i), 0);
			}
			
			player.addInventory(new PlayerInventory(playerItems, comm));
			Shop testShop = new Shop(null, shopItems, comm, "Independence");
			comm.ThrowGUIEvent(new AtShopEvent(testShop, testShop.getShopPrices(), player.getInventory().getStock(), player.getMoney(), player.getInventory().getCurrentWeight()));
		}
	}

	public void takeATurn(PlayPanel playPanel) {
		trail.advance(playerParty.getPlayer().getInventory(), gameSettings, playerParty, this);
		eventGenerator.generateRandomEvent();
	}
	
	public void updatePlayPanel(PlayPanel playPanel){
		playPanel.updatePlayPanel(day, trail.getMilesTraveled(), playerParty.getPlayer().getMoney(), playerParty.getPlayer().getInventory().getStock());
	}

	public int getDay() {
		return day;
	}

	public void setDay(int day) {
		this.day = day;
	}

	public void updateRation(eRation ration) {
		gameSettings.setRation(ration);
	}

	public void updatePace(ePace pace) {
		gameSettings.setPace(pace);
	}
	
	public Trail getTrail() {
		return trail;
	}
	
	public Party getParty(){
		return playerParty;
	}

	public void crossRiver(String method, String riverName, int riverDepth) {
		generator = new Random();
		itemList = playerParty.getPlayer().getInventory().getStock().keySet().toArray();
		playerStock = playerParty.getPlayer().getInventory().getStock();
		toRemove = (Item)itemList[generator.nextInt(itemList.length)];
		
		//Ford the river rdbtnFord 10% <= 3 feet 50% > 3 feet
		if(method.compareTo("Ford") == 0)
		{
			
			//Check if river is 3 feet deep
			int chance = generator.nextInt(100);
			if((riverDepth <= 3 && chance<=10) || (riverDepth > 3 && chance <= 50))
			{
				if(chance <= 5){
					numToRemove = generator.nextInt(playerParty.getParty().size());
					playerParty.getParty().get(numToRemove).setStatus(eStatus.dead);
					JOptionPane.showMessageDialog(null,"Your wagon flipped and "+playerParty.getParty().get(numToRemove).getName()+" drowned.");
				}
				else{
					while(playerStock.get(toRemove) < 1){
						toRemove = (Item)itemList[generator.nextInt(itemList.length)];
					}
					int numToRemove = generator.nextInt(playerStock.get(toRemove))+1;
					playerParty.getPlayer().getInventory().removeItem(toRemove, numToRemove);
					JOptionPane.showMessageDialog(null,"Your wagon flipped and you lost "+numToRemove+" "+toRemove.getItemName()+".");
				}
			}
			else{
				JOptionPane.showMessageDialog(null,"You successfully forded "+riverName+".");
			}
			
		}//Caulk the wagon and float it across rdbtnCaulk 30%
		else if(method.compareTo("Caulk") == 0)
		{
			chance = generator.nextInt(100);
			if(chance<=30)
			{
				chance = generator.nextInt(100);
				if(chance <= 5){
					int numToRemove = generator.nextInt(playerParty.getParty().size())+1;
					playerParty.getParty().get(numToRemove).setStatus(eStatus.dead);
					JOptionPane.showMessageDialog(null,"Your wagon flipped and "+playerParty.getParty().get(numToRemove).getName()+" drowned.");									
				}
				else{
					while(playerStock.get(toRemove) < 1){
						toRemove = (Item)itemList[generator.nextInt(itemList.length)];
					}
					numToRemove = generator.nextInt(playerStock.get(toRemove))+1;
					playerParty.getPlayer().getInventory().removeItem(toRemove, numToRemove);
					JOptionPane.showMessageDialog(null,"Your wagon flipped and you lost "+numToRemove+" "+toRemove.getItemName()+".");
				}
			}
			else{
				JOptionPane.showMessageDialog(null,"You successfully floated across "+riverName+".");
			}
		}//Pay a few dollars to take the ferry across rdbtnFerry
		else if(method.compareTo("Ferry") == 0)
		{
			///Check if player had enough money first
			fee = 100;
			if((playerParty.getPlayer().getMoney()-fee) > 0)
			{
				playerParty.getPlayer().setMoney(playerParty.getPlayer().getMoney()-fee);
				JOptionPane.showMessageDialog(null,"You were ferried across "+riverName+".");
			}
			else
			{
				JOptionPane.showMessageDialog(null,"Not enough money, show me the money!");
				//do nothing
			}		
		}
	
	}
	
}
